package com.arvato.minipro.controller.front.user;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.arvato.minipro.bean.bean_do.user.LoginLogDo;
import com.arvato.minipro.bean.bean_do.user.EcUserDo;
import com.arvato.minipro.bean.bean_dto.common.Query;
import com.arvato.minipro.bean.bean_dto.common.Result;
import com.arvato.minipro.bean.bean_vo.user.EcUserVo;
import com.arvato.common.config_bean.WxPlatformConfig;
import com.arvato.common.https.HttpsUtil;
import com.arvato.common.https.WxMiniproThirdRequestUtil;
import com.arvato.common.util.AESUtil;
import com.arvato.common.util.DateFormatUtil;
import com.arvato.common.util.JsonUtil;
import com.arvato.minipro.controller.BaseController;
import com.arvato.minipro.service.user.LoginLogService;
import com.arvato.minipro.service.user.EcUserService;

/***
 * 处理小程序登录相关的Controller
 * @author ZHAN655
 *
 */
@Controller
@RequestMapping("/login")
public class EcLoginController extends BaseController {

	private Logger logger = LoggerFactory.getLogger(EcLoginController.class);

	@Autowired
	private EcUserService userService;

	@Autowired
	private LoginLogService loginLogService;

	@Autowired
	private JsonUtil jsonUtil;

	@Autowired
	private WxMiniproThirdRequestUtil wxRequestUtil;

	/**
	 * 微信用户登录(普通小程序微信用户的登录)
	 * 
	 * @param code
	 *            前台wx.login()方法发过来的返回值
	 * @param nickName
	 *            微信用户昵称
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/wx/platform")
	public Result wxLogin(String code, String nickName, String avatarUrl, String appId, String method) {
		Result result = new Result(false);
		logger.info("------微信小程序普通登录-----");
		// 微信小程序的appid(每个小程序都有一个，可以在 登录微信公众平台之后，在开发设置里面找到)
		String appid = "wx936dab9b74408232";
		// 微信小程序的appid对应的秘钥，这个秘钥如果忘记了的话，可以在登录微信公众平台之后，重置秘钥，重置之后，之前秘钥作废
		String secret = "ac155389da0ef889fd091850d2a59a9e";
		String url = "https://api.weixin.qq.com/sns/jscode2session" + "?appid=" + appid + "&secret=" + secret
				+ "&js_code=" + code + "&grant_type=authorization_code";
		String resJsonStr = HttpsUtil.httpsRequest(url, "GET", null);
		logger.info("用户信息" + resJsonStr);
		String openId = null;
		Map<String, Object> map = jsonUtil.str2Map(resJsonStr);
		// 如果openId 为空的话 那么就登录失败
		if (map.get("openid") == null) {
			result.setResult(false);
			return result;
		}
		openId = map.get("openid") + "";
		String sessionKey = map.get("session_key") + "";
		// 到这一步就算登录成功了，记录下来，算作一次登录访问
		LoginLogDo loginLog = new LoginLogDo();
		loginLog.setAppid(appid);
		loginLog.setOpenId(openId);
		loginLog.setCreateTime(new Date());
		logger.info("------登录人:" + appid + "登录时间：" + DateFormatUtil.date2Str(new Date()));
		loginLog.setMethod(method);
		loginLog.setNickname(nickName);
		try {
			loginLogService.insert(loginLog);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info(nickName + "用户登录日志插入失败。");
		}
		// 根据openId查询用户
		Query query = new Query();
		query.put("wxOpenid", openId);
		EcUserVo userVo = userService.getUserByQuery(query);
		EcUserDo userDo = new EcUserDo();
		if (userVo != null) {
			// 看看是否要更新用户信息
			if (userVo.getAppid() == null) {
				userDo.setAppid(appId);
			}
			// 之前没有存用户的微信头像 或者是用户更换了微信头像
			if (avatarUrl != null) {
				if (userVo.getAvatarUrl() == null || !userVo.getAvatarUrl().equals(avatarUrl)) {
					userDo.setAvatarUrl(avatarUrl);
				}
			}
			if (userDo.getAppid() != null || userDo.getWxUnionid() != null || userDo.getAvatarUrl() != null) {
				userDo.setUserId(userVo.getUserId());
				try {
					userService.update(userDo);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			result.setResult(true);
			userVo.setSessionKey(sessionKey);
			result.setData(userVo);
			return result;
		}
		userDo.setWxOpenid(openId);
		userDo.setAppid(appId);
		userDo.setNickname(nickName);
		userDo.setAvatarUrl(avatarUrl);
		userDo.setCreateDate(new Date());
		userDo.setStatus(1);
		int row;
		try {
			row = userService.insert(userDo);
			if (row == 1) {
				userVo = userService.getUserById(userDo.getUserId());
				userVo.setSessionKey(sessionKey);
				result.setData(userVo);
				result.setResult(true);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 微信用户登录三方平台托管下的微信小程序
	 * 
	 * @param code
	 *            前台wx.login()方法发过来的返回值
	 * @param nickName
	 *            微信用户昵称
	 * @param avatarUrl
	 *            微信用户头像链接
	 * @param appId
	 *            三方平台下的小程序appid
	 * @param method
	 *            method值为1，2，3，4，5 等。表示不同的二维码入口
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/wx")
	public Result wxPlatformLogin(String code, String nickName, String avatarUrl, String appId, String method) {
		if (appId == null || appId.equals("") || appId.equals("undefined")) {
			// wx81a75e072738a79d是三方平台绑定的开发小程序的ID
			appId = "wx81a75e072738a79d";
		}
		logger.info("------授权给平台的小程序微信登录-----");

		// 微信小程序的appid(每个小程序都有一个，可以在 登录微信公众平台之后，在开发设置里面找到)
		// 用户授权给我们之后 我们就会得到用户的appid 存在表里面了
		Result result = wxRequestUtil.getComponentAccessToken();
		// 如果访问令牌过期了或者不存在直接返回
		if (result.getCode() != 200) {
			return result;
		}
		String accessToken = result.getData().toString();
		String url = "https://api.weixin.qq.com/sns/component/jscode2session" + "?appid=" + appId + "&js_code=" + code
				+ "&grant_type=authorization_code" + "&component_appid=" + WxPlatformConfig.WX_APPID
				+ "&component_access_token=" + accessToken;
		logger.info("用户请求登录url" + url);
		String resJsonStr = HttpsUtil.httpsRequest(url, "GET", null);
		logger.info("用户信息" + resJsonStr);
		String openId = null;
		Map<String, Object> map = jsonUtil.str2Map(resJsonStr);
		// 如果openId 为空的话 那么就登录失败
		if (map.get("openid") == null) {
			result.setResult(false);
			return result;
		}
		openId = map.get("openid") + "";
		String sessionKey = map.get("session_key") + "";
		// 到这一步就算登录成功了，记录下来，算作一次登录访问
		LoginLogDo loginLog = new LoginLogDo();
		loginLog.setAppid(appId);
		loginLog.setOpenId(openId);
		loginLog.setCreateTime(new Date());
		logger.info("------登录人:" + appId + "登录时间：" + DateFormatUtil.date2Str(new Date()));
		loginLog.setMethod(method);
		loginLog.setNickname(nickName);
		try {
			loginLogService.insert(loginLog);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info(nickName + "用户登录日志插入失败。");
		}
		// 根据openId查询用户
		Query query = new Query();
		query.put("wxOpenid", openId);
		EcUserVo userVo = userService.getUserByQuery(query);
		EcUserDo userDo = new EcUserDo();
		if (userVo != null) {
			// 看看是否要更新用户信息
			if (userVo.getAppid() == null) {
				userDo.setAppid(appId);
			}
			// 之前没有存用户的微信头像 或者是用户更换了微信头像
			if (avatarUrl != null) {
				if (userVo.getAvatarUrl() == null || !userVo.getAvatarUrl().equals(avatarUrl)) {
					userDo.setAvatarUrl(avatarUrl);
				}
			}
			if (userDo.getAppid() != null || userDo.getWxUnionid() != null || userDo.getAvatarUrl() != null) {
				userDo.setUserId(userVo.getUserId());
				try {
					userService.update(userDo);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			result.setResult(true);
			userVo.setSessionKey(sessionKey);
			result.setData(userVo);
			return result;
		}
		userDo.setWxOpenid(openId);
		userDo.setAppid(appId);
		userDo.setNickname(nickName);
		userDo.setAvatarUrl(avatarUrl);
		userDo.setCreateDate(new Date());
		userDo.setStatus(1);
		int row;
		try {
			row = userService.insert(userDo);
			if (row == 1) {
				userVo = userService.getUserById(userDo.getUserId());
				userVo.setSessionKey(sessionKey);
				result.setData(userVo);
				result.setResult(true);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 接受一个用户被加密后的unionId 根据解密参数 解出unionId并且存储到数据库
	 * 
	 * @param encryptedData
	 *            被加密的数据
	 * @param iv
	 *            解密参数之一
	 * @param sessionKey
	 *            解密参数之一
	 * @param userId
	 *            用户Id
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/unionid")
	public void saveUnionId(String encryptedData, String iv, String sessionKey, String userId) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			byte[] resultByte = AESUtil.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey),
					Base64.decodeBase64(iv));
			if (null != resultByte && resultByte.length > 0) {
				String userInfo = new String(resultByte, "UTF-8");
				map.put("status", "1");
				map.put("msg", "解密成功");
				map.put("userInfo", userInfo);
			} else {
				map.put("status", "0");
				map.put("msg", "解密失败");
			}
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		Object object = map.get("userInfo");
		if(object != null) {
			Map<String, Object> userInfoMap = jsonUtil.str2Map(object + "");
			String unionId = userInfoMap.get("unionId") + "";
			System.out.println("unionId为:" + unionId);
			// 更新用户的unionid 
			// 虽然这个地方应该从缓存(redis等)中取出用户的信息
			// 看看是和这个unionid一样，一样就什么都不做，不一样就更新数据库
			// 但是我们没缓存啊! 哇哈哈哈哈
			EcUserDo userDo = new EcUserDo();
			userDo.setUserId(userId);
			userDo.setWxUnionid(unionId);
			userService.update(userDo);
		}
	}

}
